﻿using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.Editors;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Xpo;
using EasyXaf.EntityDesigner.BusinessObjects;
using EasyXaf.EntityDesigner.BusinessObjects.Entities;
using EasyXaf.EntityDesigner.BusinessObjects.Entities.Appearances;
using EasyXaf.EntityDesigner.BusinessObjects.Enums;
using System.ComponentModel;

namespace EasyXaf.EntityDesigner.BusinessObjects.Entities.EntityProperties;

/// <summary>
/// 实体属性
/// </summary>
[XafDisplayName("实体属性")]
[XafDefaultProperty(nameof(DisplayName))]
public partial class EntityProperty : BaseObject
{
    private string _name;
    private string _caption;
    private string _description;
    private double _order;
    private string _columnName;
    private DefaultBoolean _isEditable;
    private DefaultBoolean _isCloneable;
    private DefaultBoolean _isBrowsable;
    private DefaultBoolean _isVisibleInDetailView;
    private DefaultBoolean _isVisibleInListView;
    private DefaultBoolean _isVisibleInLookupListView;
    private DefaultBoolean _isVisibleInReports;
    private DefaultBoolean _isImmediatePost;
    private DefaultBoolean _noForeignKeyConstraints;
    private bool _isPrimaryKey;
    private DefaultBoolean _isPersistent;
    private DefaultBoolean _isFetchOnly;
    private bool _isReadonly;
    private DefaultBoolean _isNullable;
    private string _propertyEditor;
    private PropertyType _propertyType;
    private int _stringLength;
    private Enumeration _enumType;
    private string _enumTypeFullName;
    private Entity _entityType;
    private string _defaultValue;
    private string _columnDefaultValue;
    private DataSourceType _dataSourceType;
    private string _dataSource;
    private Entity _entity;

    /// <summary>
    /// 名称
    /// </summary>
    [XafDisplayName("名称")]
    [RuleRequiredField]
    public string Name
    {
        get => _name;
        set => SetPropertyValue(nameof(Name), ref _name, value);
    }

    /// <summary>
    /// 显示名称
    /// </summary>
    [XafDisplayName("显示名称")]
    public string DisplayName
    {
        get => GetDisplayName();
    }

    /// <summary>
    /// 标题
    /// </summary>
    [XafDisplayName("标题")]
    public string Caption
    {
        get => _caption;
        set => SetPropertyValue(nameof(Caption), ref _caption, value);
    }

    /// <summary>
    /// 描述
    /// </summary>
    [XafDisplayName("描述")]
    [Size(SizeAttribute.Unlimited)]
    public string Description
    {
        get => _description;
        set => SetPropertyValue(nameof(Description), ref _description, value);
    }

    /// <summary>
    /// 顺序
    /// </summary>
    [XafDisplayName("顺序")]
    public double Order
    {
        get => _order;
        set => SetPropertyValue(nameof(Order), ref _order, value);
    }

    /// <summary>
    /// 列名
    /// </summary>
    [XafDisplayName("列名")]
    public string ColumnName
    {
        get => _columnName;
        set => SetPropertyValue(nameof(ColumnName), ref _columnName, value);
    }

    /// <summary>
    /// 可编辑
    /// </summary>
    [XafDisplayName("可编辑")]
    public DefaultBoolean IsEditable
    {
        get => _isEditable;
        set => SetPropertyValue(nameof(IsEditable), ref _isEditable, value);
    }

    /// <summary>
    /// 可克隆
    /// </summary>
    [XafDisplayName("可克隆")]
    public DefaultBoolean IsCloneable
    {
        get => _isCloneable;
        set => SetPropertyValue(nameof(IsCloneable), ref _isCloneable, value);
    }

    /// <summary>
    /// 可浏览
    /// </summary>
    [XafDisplayName("可浏览")]
    public DefaultBoolean IsBrowsable
    {
        get => _isBrowsable;
        set => SetPropertyValue(nameof(IsBrowsable), ref _isBrowsable, value);
    }

    /// <summary>
    /// 显示在详情视图中
    /// </summary>
    [XafDisplayName("显示在详情视图中")]
    public DefaultBoolean IsVisibleInDetailView
    {
        get => _isVisibleInDetailView;
        set => SetPropertyValue(nameof(IsVisibleInDetailView), ref _isVisibleInDetailView, value);
    }

    /// <summary>
    /// 显示在列表视图中
    /// </summary>
    [XafDisplayName("显示在列表视图中")]
    public DefaultBoolean IsVisibleInListView
    {
        get => _isVisibleInListView;
        set => SetPropertyValue(nameof(IsVisibleInListView), ref _isVisibleInListView, value);
    }

    /// <summary>
    /// 显示在查找列表视图中
    /// </summary>
    [XafDisplayName("显示在查找列表视图中")]
    public DefaultBoolean IsVisibleInLookupListView
    {
        get => _isVisibleInLookupListView;
        set => SetPropertyValue(nameof(IsVisibleInLookupListView), ref _isVisibleInLookupListView, value);
    }

    /// <summary>
    /// 显示在报表中
    /// </summary>
    [XafDisplayName("显示在报表中")]
    public DefaultBoolean IsVisibleInReports
    {
        get => _isVisibleInReports;
        set => SetPropertyValue(nameof(IsVisibleInReports), ref _isVisibleInReports, value);
    }

    /// <summary>
    /// 即时更新
    /// </summary>
    [XafDisplayName("即时更新")]
    public DefaultBoolean IsImmediatePost
    {
        get => _isImmediatePost;
        set => SetPropertyValue(nameof(IsImmediatePost), ref _isImmediatePost, value);
    }

    /// <summary>
    /// 无外键约束
    /// </summary>
    [XafDisplayName("无外键约束")]
    [Appearance("只有属性类型为Entity实体时才显示无外键约束", Criteria = "PropertyType != 'Entity'", Visibility = ViewItemVisibility.Hide)]
    public DefaultBoolean NoForeignKeyConstraints
    {
        get => _noForeignKeyConstraints;
        set => SetPropertyValue(nameof(NoForeignKeyConstraints), ref _noForeignKeyConstraints, value);
    }

    /// <summary>
    /// 主键
    /// </summary>
    [XafDisplayName("主键")]
    public bool IsPrimaryKey
    {
        get => _isPrimaryKey;
        set => SetPropertyValue(nameof(IsPrimaryKey), ref _isPrimaryKey, value);
    }

    /// <summary>
    /// 持久化
    /// </summary>
    [XafDisplayName("持久化")]
    public DefaultBoolean IsPersistent
    {
        get => _isPersistent;
        set => SetPropertyValue(nameof(IsPersistent), ref _isPersistent, value);
    }

    /// <summary>
    /// 只获取
    /// </summary>
    [XafDisplayName("只获取")]
    [VisibleInListView(false)]
    public DefaultBoolean IsFetchOnly
    {
        get => _isFetchOnly;
        set => SetPropertyValue(nameof(IsFetchOnly), ref _isFetchOnly, value);
    }

    /// <summary>
    /// 只读
    /// </summary>
    [XafDisplayName("只读")]
    public bool IsReadonly
    {
        get => _isReadonly;
        set => SetPropertyValue(nameof(IsReadonly), ref _isReadonly, value);
    }

    /// <summary>
    /// 可为Null
    /// </summary>
    [XafDisplayName("可为Null")]
    public DefaultBoolean IsNullable
    {
        get => _isNullable;
        set => SetPropertyValue(nameof(IsNullable), ref _isNullable, value);
    }

    /// <summary>
    /// 属性编辑器
    /// </summary>
    [XafDisplayName("属性编辑器")]
    public string PropertyEditor
    {
        get => _propertyEditor;
        set => SetPropertyValue(nameof(PropertyEditor), ref _propertyEditor, value);
    }

    /// <summary>
    /// 属性类型
    /// </summary>
    [XafDisplayName("属性类型")]
    public PropertyType PropertyType
    {
        get => _propertyType;
        set => SetPropertyValue(nameof(PropertyType), ref _propertyType, value);
    }

    /// <summary>
    /// 字符串长度
    /// </summary>
    [XafDisplayName("字符串长度")]
    [Appearance("只有属性类型为字符串时才显示字符串长度", Criteria = "PropertyType != 'String'", Visibility = ViewItemVisibility.Hide)]
    public int StringLength
    {
        get => _stringLength;
        set => SetPropertyValue(nameof(StringLength), ref _stringLength, value);
    }

    /// <summary>
    /// 枚举类型
    /// </summary>
    [XafDisplayName("枚举类型")]
    [DataSourceProperty(nameof(EnumTypeDataSource))]
    [Appearance("只有属性类型为枚举时才显示枚举类型", Criteria = "PropertyType != 'Enumeration'", Visibility = ViewItemVisibility.Hide)]
    public Enumeration EnumType
    {
        get => _enumType;
        set => SetPropertyValue(nameof(EnumType), ref _enumType, value);
    }

    /// <summary>
    /// 枚举全名
    /// </summary>
    [XafDisplayName("枚举全名")]
    [VisibleInListView(false)]
    [Appearance("只有属性类型为枚举时才显示枚举全名", Criteria = "PropertyType != 'Enumeration'", Visibility = ViewItemVisibility.Hide)]
    public string EnumTypeFullName
    {
        get => _enumTypeFullName;
        set => SetPropertyValue(nameof(EnumTypeFullName), ref _enumTypeFullName, value);
    }

    /// <summary>
    /// 实体类型
    /// </summary>
    [XafDisplayName("实体类型")]
    [DataSourceProperty(nameof(EntityTypeDataSource))]
    [Appearance("只有属性类型为实体或实体列表时才显示实体类型", Criteria = "PropertyType != 'Entity' And PropertyType != 'EntityCollection'", Visibility = ViewItemVisibility.Hide)]
    public Entity EntityType
    {
        get => _entityType;
        set => SetPropertyValue(nameof(EntityType), ref _entityType, value);
    }

    /// <summary>
    /// 默认值(C#)
    /// </summary>
    [XafDisplayName("默认值(C#)")]
    public string DefaultValue
    {
        get => _defaultValue;
        set => SetPropertyValue(nameof(DefaultValue), ref _defaultValue, value);
    }

    /// <summary>
    /// 列默认值
    /// </summary>
    [XafDisplayName("列默认值")]
    [VisibleInListView(false)]
    [Appearance("只有属性类型小于10(Guid)时才显示列默认值", Criteria = "PropertyType >= 10", Visibility = ViewItemVisibility.Hide)]
    public string ColumnDefaultValue
    {
        get => _columnDefaultValue;
        set => SetPropertyValue(nameof(ColumnDefaultValue), ref _columnDefaultValue, value);
    }

    /// <summary>
    /// 数据源类型
    /// </summary>
    [XafDisplayName("数据源类型")]
    [VisibleInListView(false)]
    [Appearance("当属性类型为Entity或EntityCollection时才显示数据源类型", Criteria = "PropertyType != 'Entity' And PropertyType != 'EntityCollection'", Visibility = ViewItemVisibility.Hide)]
    public DataSourceType DataSourceType
    {
        get => _dataSourceType;
        set => SetPropertyValue(nameof(DataSourceType), ref _dataSourceType, value);
    }

    /// <summary>
    /// 数据源
    /// </summary>
    [XafDisplayName("数据源")]
    [VisibleInListView(false)]
    [Appearance("当属性类型为Entity或EntityCollection并且数据源类型不为None时才显示数据源", Criteria = "(PropertyType != 'Entity' And PropertyType != 'EntityCollection') || DataSourceType = 0", Visibility = ViewItemVisibility.Hide)]
    public string DataSource
    {
        get => _dataSource;
        set => SetPropertyValue(nameof(DataSource), ref _dataSource, value);
    }

    /// <summary>
    /// 实体
    /// </summary>
    [XafDisplayName("实体")]
    [Association("Properties-Entity")]
    public Entity Entity
    {
        get => _entity;
        set => SetPropertyValue(nameof(Entity), ref _entity, value);
    }

    /// <summary>
    /// 类型名称
    /// </summary>
    [XafDisplayName("类型名称")]
    [Browsable(false)]
    public string TypeName
    {
        get => GetTypeName();
    }

    /// <summary>
    /// 类型概要
    /// </summary>
    [XafDisplayName("类型概要")]
    public string TypeSummary
    {
        get => GetTypeSummary();
    }

    /// <summary>
    /// PropertyTypeImage
    /// </summary>
    [Browsable(false)]
    public string PropertyTypeImage
    {
        get => GetPropertyTypeImage();
    }

    /// <summary>
    /// 图像名
    /// </summary>
    [XafDisplayName("图像名")]
    [Browsable(false)]
    public string ImageName
    {
        get => GetImageName();
    }

    /// <summary>
    /// Appearances
    /// </summary>
    [Browsable(false)]
    [Association("TargetProperty-Appearances")]
    public XPCollection<Appearance> Appearances
    {
        get => GetCollection<Appearance>(nameof(Appearances));
    }

    [Browsable(false)]
    public IList<Enumeration> EnumTypeDataSource
    {
        get => GetEnumTypeDataSource();
    }

    [Browsable(false)]
    public IList<Entity> EntityTypeDataSource
    {
        get => GetEntityTypeDataSource();
    }

    public EntityProperty(Session session)
        : base(session)
    {
    }

    private partial string GetDisplayName();

    private partial string GetTypeName();

    private partial string GetTypeSummary();

    private partial string GetPropertyTypeImage();

    private partial string GetImageName();

    private partial IList<Enumeration> GetEnumTypeDataSource();

    private partial IList<Entity> GetEntityTypeDataSource();
}
